module klang.编译.APSInt.APSInt_;
import 全局;
import klang.编译.APInt.APInt_: APInt_;
import APInt = klang.编译.APInt.APInt_;
import klang.编译.类型.枚举值.枚举值_: 字符_;
import klang.编译.核心.核心_: 最小, 最大;
class APSInt_ : APInt_ {
    bool IsUnsigned;
    this() {
        super();
        this.IsUnsigned = false;
    }
    this(uint BitWidth, bool isUnsigned = true) {
        super(BitWidth, 0);
        this.IsUnsigned = isUnsigned;
    }
    this(APInt_ I, bool isUnsigned = true) {
        super(I);
        this.IsUnsigned = isUnsigned;
    }
    this(dstring Str) {
        super();
        uint NumBits = (cast(uint)(((Str.length * 64) / 19) + 2));
        APInt_ Tmp = new APInt_(NumBits, Str, /*radix=*/ 10);
        if (Str[0] == 字符_.减号) {
            uint MinBits = Tmp.getMinSignedBits();
            if (MinBits < NumBits) {
                Tmp = Tmp.trunc((cast(uint)(最大(1, MinBits))));
            }
            APSInt_ R = new APSInt_(Tmp, /*isUnsigned=*/ false);
            this.U = R.U;
            this.BitWidth = R.BitWidth;
            this.IsUnsigned = R.IsUnsigned;
            return;
        }
        uint ActiveBits = Tmp.getActiveBits();
        if (ActiveBits < NumBits) {
            Tmp = Tmp.trunc((cast(uint)(最大(1, ActiveBits))));
        }
        APSInt_ R2 = new APSInt_(Tmp, /*isUnsigned=*/ true);
        this.U = R2.U;
        this.BitWidth = R2.BitWidth;
        this.IsUnsigned = R2.IsUnsigned;
        return;
    }
    bool isSigned() { return !this.IsUnsigned; }
    bool isUnsigned() { return this.IsUnsigned; }
    void setIsUnsigned(bool Val) { this.IsUnsigned = Val; }
    void setIsSigned(bool Val) { this.IsUnsigned = !Val; }
    long getExtValue() {
        return this.isSigned() ? this.getSExtValue() : this.getZExtValue();
    }
    APSInt_ extend(uint width) {
        if (this.IsUnsigned) {
            return new APSInt_(this.APInt_.zext(width), this.IsUnsigned);
        }
        else {
            return new APSInt_(this.APInt_.sext(width), this.IsUnsigned);
        }
    }
    APSInt_ extOrTrunc(uint width) {
        if (this.IsUnsigned) {
            return new APSInt_(this.APInt_.zextOrTrunc(width), this.IsUnsigned);
        }
        else {
            return new APSInt_(this.APInt_.sextOrTrunc(width), this.IsUnsigned);
        }
    }
    APSInt_ Op余等(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        if (this.IsUnsigned) {
            APInt_ R = this.urem(RHS);
            this.U = R.U;
            this.BitWidth = R.BitWidth;
        }
        else {
            APInt_ R = this.srem(RHS);
            this.U = R.U;
            this.BitWidth = R.BitWidth;
        }
        return this;
    }
    APSInt_ Op除等(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        if (this.IsUnsigned) {
            APInt_ R = this.udiv(RHS);
            this.U = R.U;
            this.BitWidth = R.BitWidth;
        }
        else {
            APInt_ R = this.sdiv(RHS);
            this.U = R.U;
            this.BitWidth = R.BitWidth;
        }
        return this;
    }
    APSInt_ Op余(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        return this.IsUnsigned ? new APSInt_(this.urem(RHS), true) : new APSInt_(this.srem(RHS), false);
    }
    APSInt_ Op除(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        return this.IsUnsigned ? new APSInt_(this.udiv(RHS), true) : new APSInt_(this.sdiv(RHS), false);
    }
    APSInt_ Op右移(uint Amt) {
        return this.IsUnsigned ? new APSInt_(this.lshr(Amt), true) : new APSInt_(this.ashr(Amt), false);
    }
    APSInt_ Op右移等(uint Amt) {
        if (this.IsUnsigned) {
            this.lshrInPlace(Amt);
        }
        else {
            this.ashrInPlace(Amt);
        }
        return this;
    }
    bool Op小于(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        return this.IsUnsigned ? this.ult(RHS) : this.slt(RHS);
    }
    bool Op小于(long RHS) {
        return .compareValues(this, .get(RHS)) < 0;
    }
    bool Op小于等于(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        return this.IsUnsigned ? this.ule(RHS) : this.sle(RHS);
    }
    bool Op小于等于(long RHS) {
        return .compareValues(this, .get(RHS)) <= 0;
    }
    bool Op大于(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        return this.IsUnsigned ? this.ugt(RHS) : this.sgt(RHS);
    }
    bool Op大于(long RHS) {
        return .compareValues(this, .get(RHS)) > 0;
    }
    bool Op大于等于(APSInt_ RHS) {
        assert(this.IsUnsigned == RHS.IsUnsigned, "Signedness mismatch!"c);
        return this.IsUnsigned ? this.uge(RHS) : this.sge(RHS);
    }
    bool Op大于等于(long RHS) {
        return .compareValues(this, .get(RHS)) >= 0;
    }
    bool Op不等于(APSInt_ RHS) {
        return !this.Op等于(RHS);
    }
    bool Op不等于(long RHS) {
        return .compareValues(this, .get(RHS)) != 0;
    }
    bool Op等于(APSInt_ RHS) {
        return this.eq(RHS);
    }
    bool Op等于(long RHS) {
        return .compareValues(this, .get(RHS)) == 0;
    }
}
APSInt_ getMaxValue(uint numBits, bool Unsigned) {
    return new APSInt_(Unsigned ? APInt.getMaxValue(numBits) : APInt.getSignedMaxValue(numBits), Unsigned);
}
APSInt_ getMinValue(uint numBits, bool Unsigned) {
    return new APSInt_(Unsigned ? APInt.getMinValue(numBits) : APInt.getSignedMinValue(numBits), Unsigned);
}
bool isSameValue(APSInt_ I1, APSInt_ I2) {
    return .compareValues(I1, I2) == 0;
}
int compareValues(APSInt_ I1, APSInt_ I2) {
    if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) {
        return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
    }
    // Check for a bit-width mismatch.
    if (I1.getBitWidth() > I2.getBitWidth()) {
        return .compareValues(I1, I2.extend(I1.getBitWidth()));
    }
    if (I2.getBitWidth() > I1.getBitWidth()) {
        return .compareValues(I1.extend(I2.getBitWidth()), I2);
    }
    // We have a signedness mismatch. Check for negative values and do an
    // unsigned compare if both are positive.
    if (I1.isSigned()) {
        assert(!I2.isSigned(), "Expected signed mismatch"c);
        if (I1.isNegative()) {
            return -1;
        }
    }
    else {
        assert(I2.isSigned(), "Expected signed mismatch"c);
        if (I2.isNegative()) {
            return 1;
        }
    }
    return I1.compare(I2);
}
APSInt_ get(long X) { return new APSInt_(new APInt_(64, X), false); }
APSInt_ getUnsigned(ulong X) { return new APSInt_(new APInt_(64, X), true); }
